#include "Tetra4NodeShpFunc.h"
#include "DataStructure/Common/Real.h"

using SG::Algebra::Matrixd;
using SG::DataStructure::Common::Real;
using SG::FEMSolver::Element::Tetra4NodeShpFunc;

Tetra4NodeShpFunc::Tetra4NodeShpFunc ()
: NSet (), DNDxiSet ()
{}

/** @brief 计算积分点处形函数及形函数对参数坐标导数
 * 
 * 缓存各个积分点处的计算结果，避免下一次积分点循环时重复计算（内存换取计算时间）
 */
void Tetra4NodeShpFunc::Compute (const SG::DataStructure::FEM::IntegPointArray& integPoints)
{
    const auto nGauss = integPoints.size ();
    NSet.resize (nGauss);
    DNDxiSet.resize (nGauss);

    for (std::size_t index{0}; index < nGauss; ++index)
    {
        const Real& xi{integPoints[index].m_x};
        const Real& eta{integPoints[index].m_y};
        const Real& zeta{integPoints[index].m_z};

        // 计算形状函数
        NSet[index] = Matrixd (4, 1);
        NSet[index] (0, 0) = (1.0 - xi - eta - zeta);  // N1
        NSet[index] (1, 0) = xi;                       // N2
        NSet[index] (2, 0) = eta;                      // N3
        NSet[index] (3, 0) = zeta;                     // N4

        // 计算形状函数导数
        DNDxiSet[index] = Matrixd (3, 4);
        DNDxiSet[index] (0, 0) = -1.0;  // dN1/dxi
        DNDxiSet[index] (1, 0) = -1.0;  // dN1/deta
        DNDxiSet[index] (2, 0) = -1.0;  // dN1/dzeta

        DNDxiSet[index] (0, 1) =  1.0;  // dN2/dxi
        DNDxiSet[index] (1, 1) =  0.0;  // dN2/deta
        DNDxiSet[index] (2, 1) =  0.0;  // dN2/dzeta

        DNDxiSet[index] (0, 2) =  0.0;  // dN3/dxi
        DNDxiSet[index] (1, 2) =  1.0;  // dN3/deta
        DNDxiSet[index] (2, 2) =  0.0;  // dN3/dzeta

        DNDxiSet[index] (0, 3) =  0.0;  // dN4/dxi
        DNDxiSet[index] (1, 3) =  0.0;  // dN4/deta
        DNDxiSet[index] (2, 3) =  1.0;  // dN4/dzeta
    }
}